You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I changed the sync Java TurboModule string return path to copy the jstring with GetStringRegion into a 256 char stack buffer (heap above that), going from 3 JNI calls (GetStringLength, GetStringChars, ReleaseStringChars) -> 2 (GetStringLength, GetStringRegion) per call.
I did 100_000 calls of SampleTurboModule.getString(s)
Phase
Median ms
Min
Max
Without fix, round 1
86
83
104
With fix, round 1
82
78
87
Without fix, round 2
93
85
124
With fix, round 2
82.5
77
92
For some things like NativeAppearance.getColorScheme() I got upto 19% improvement.
The 256 number is just a POC. We can try 512 or 1024 or something. I am happy to discuss on this .
Changelog:
[ANDROID][CHANGED] - Use GetStringRegion for JavaTurboModule to reduce JNI calls from 3->2
Test Plan:
I ran maestro tests locally . Everything seems to pass.
I also asked claude to create a set of test cases with different string types(text, String , emojis) in turbo module to see nothing breaks
meta-claBot
added
the
CLA Signed
This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.
label
Sep 21, 2026
Cool idea! I wonder if there's higher impact areas for this beyond turbomodule return values (eg WritableNativeMap / WritableNativeArray) - and what the right max stack size to use is.
Worth measuring too: the 2nd param to GetStringChars tells you whether a copy was made (and whether this is just pinning memory vs doing an extra copy).
Worth measuring too: the 2nd param to GetStringChars tells you whether a copy was made (and whether this is just pinning memory vs doing an extra copy).
I checked the copy thing with the old code, GetStringChars returned isCopy=1 for every string I tried, compressed Latin-1 and uncompressed CJK, different lengths(256,512, 1024,4096). So it always allocates a temporary buffer, copies, and frees it in ReleaseStringChars. With GetStringRegion the copy count stays the same (into my buffer, then into the JSI string) but we have one less JNI call and no malloc/free pair
Cool idea! I wonder if there's higher impact areas for this beyond turbomodule return values (eg WritableNativeMap / WritableNativeArray) - and what the right max stack size to use is.
Also I asked claude to create a quick POC accordingly. One more observation here is , we are using val->tostring instead of val->toStdString. So B column is essentially just that. Since we are having JString , using toStdString is worth .
Value
A toString() (current)
B toStdString()
C GetStringRegion + utf16toUTF8
B vs A
C vs A
11 ASCII
0.614
0.474
0.431
-23%
-30%
100 ASCII
0.800
0.654
0.603
-18%
-25%
300 ASCII
1.175
1.022
1.034
-13%
-12%
1000 ASCII
2.508
2.320
2.375
-7.5%
-5%
100 CJK
1.006
0.863
0.744
-14%
-26%
This branch has not been deployed
No deployments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CLA SignedThis label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.Shared with MetaApplied via automation to indicate that an Issue or Pull Request has been shared with the team.
2 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary:
I changed the sync Java TurboModule string return path to copy the jstring with
GetStringRegioninto a 256 char stack buffer (heap above that), going from 3 JNI calls (GetStringLength,GetStringChars,ReleaseStringChars) -> 2 (GetStringLength,GetStringRegion) per call.I did 100_000 calls of
SampleTurboModule.getString(s)For some things like
NativeAppearance.getColorScheme()I got upto 19% improvement.The 256 number is just a POC. We can try 512 or 1024 or something. I am happy to discuss on this .
Changelog:
[ANDROID][CHANGED] - Use GetStringRegion for JavaTurboModule to reduce JNI calls from 3->2
Test Plan:
I ran maestro tests locally . Everything seems to pass.
I also asked claude to create a set of test cases with different string types(text, String , emojis) in turbo module to see nothing breaks